#include "ButtonPage.h"
#include "../../Utility/XXlogger.h"

XX_KEY_C(ButtonPage,kFirstPage,"firstPage")
XX_KEY_C(ButtonPage,kPreviousPage,"previousPage")
XX_KEY_C(ButtonPage,kNextPage,"nextPage")
XX_KEY_C(ButtonPage,kLastPage,"lastPage")
XX_KEY_C(ButtonPage,kPageIndicator,"pageIndicator")
XX_KEY_C(ButtonPage,kPageSwitch,"pageSwitch")

XX_KEY_C(ButtonPage,kReset,"reset")
XX_KEY_C(ButtonPage,kResetParamCount,"resetParamCount")
XX_KEY_C(ButtonPage,kResetParamCountPerPage,"resetParamCountPerPage")
XX_KEY_C(ButtonPage,kResetParamPageIndex,"resetParamPageIndex")

XX_KEY_C(ButtonPage,kGetCurrentPageIndex,"getCurrentPageIndex")
XX_KEY_C(ButtonPage,kGetPageCount,"getPageCount")
XX_KEY_C(ButtonPage,kGetCountPerPage,"getCountPerPage")

XX_KEY_C(ButtonPage,kSigNeedUpdate,"sigNeedUpdate")

ButtonPage::ButtonPage(QObject *parent) : ShellBase(parent)
{
    _count = 0;
    _pageIndex = -1;
    _pageCount = 0;
}

void ButtonPage::shell(QAbstractButton *first, QAbstractButton *previous, QLabel *page, QAbstractButton *next, QAbstractButton *last, QLineEdit *pageSwitch){
    TargetMap map;
    if(first) map[kFirstPage] = first;
    if(previous) map[kPreviousPage] = previous;
    if(next) map[kNextPage] = next;
    if(last) map[kLastPage] = last;
    if(page)  map[kPageIndicator] = page;
    if(pageSwitch) map[kPageSwitch] = pageSwitch;
    ShellBase::shell(map);
}

QVariant ButtonPage::action(const QString &action, const QVariant &param){
    if(action == kReset){
        QVariantMap map = param.toMap();
        int count = map.value(kResetParamCount,0).toInt();
        int countPerPage = map.value(kResetParamCountPerPage,0).toInt();
        int pageIndex = map.value(kResetParamPageIndex,0).toInt();
        reset(count,countPerPage,pageIndex);
    }
    else if(action == kNextPage){
        nextPage();
    }
    else if(action == kPreviousPage){
        previousPage();
    }
    else if(action == kGetCurrentPageIndex){
        return getCurrentPageIndex();
    }
    else if(action == kGetPageCount){
        return getPageCount();
    }
    else if(action == kGetCountPerPage){
        return getCountPerPage();
    }
    else{

    }
    return QVariant();
}
void ButtonPage::insertItem(int index){
    bool needUpdate = false;
    int startOfPage =_pageIndex*_countPerPage;
    int endOfPage =startOfPage+_countPerPage;
    if(index<endOfPage){
        needUpdate = true;
    }

    setCountLess(_count+1,needUpdate);
    if(needUpdate){
        emit sigEvent(kSigNeedUpdate,QVariant());
    }
}
void ButtonPage::appendItem(){
    setCount1(_count+1);
}
void ButtonPage::removeItemAtIndex(int index){
    bool needUpdate = false;
    int startOfPage =_pageIndex*_countPerPage;
    int endOfPage =startOfPage+_countPerPage;
    if(index<endOfPage){
        needUpdate = true;
    }

    setCountLess(_count-1,needUpdate);
    if(needUpdate){
        emit sigEvent(kSigNeedUpdate,QVariant());
    }
}
void ButtonPage::removeItemLast(){
    setCount1(_count-1);
}
bool ButtonPage::isCurrentPage(int index){
    int startOfPage =_pageIndex*_countPerPage;
    int endOfPage =startOfPage+_countPerPage;
    return index>=startOfPage && index<endOfPage;
}

void ButtonPage::nextPage(){
    setPageIndex1(_pageIndex+1);
}
void ButtonPage::previousPage(){
    setPageIndex1(_pageIndex-1);
}
void ButtonPage::reset(int count, int countPerPage, int pageIndex){
    _countPerPage = countPerPage;

    bool needUpdate = false;
    setCountLess(count,needUpdate);
    setPageIndexLess(pageIndex,needUpdate);
    if(needUpdate){
        emit sigEvent(kSigNeedUpdate,QVariant());
    }
}
int ButtonPage::getCurrentPageIndex(){
    return _pageIndex;
}
int ButtonPage::getPageCount(){
    return _pageCount;
}
int ButtonPage::getCountPerPage(){
    return _countPerPage;
}

void ButtonPage::installTarget(const QString &name, QObject *target){
    if(name == kFirstPage || name == kPreviousPage || name == kNextPage || name == kLastPage){
        QAbstractButton *button = qobject_cast<QAbstractButton*>(target);
        if(name == kFirstPage) connect(button,&QAbstractButton::clicked,this,&ButtonPage::button_firstPage_onClicked);
        if(name == kPreviousPage) connect(button,&QAbstractButton::clicked,this,&ButtonPage::button_previousPage_onClicked);
        if(name == kNextPage) connect(button,&QAbstractButton::clicked,this,&ButtonPage::button_nextPage_onClicked);
        if(name == kLastPage) connect(button,&QAbstractButton::clicked,this,&ButtonPage::button_lastPage_onClicked);
    }
    else if(name == kPageSwitch){
        QLineEdit *lineEdit = qobject_cast<QLineEdit*>(target);
        if(lineEdit){
            connect(lineEdit,&QLineEdit::textEdited,this,&ButtonPage::lineEdit_pageSwitch_onTextEdited);
            connect(lineEdit,&QLineEdit::editingFinished,this,&ButtonPage::lineEdit_pageSwitch_onEditingFinished);
        }
    }
    else {

    }
}
void ButtonPage::uninstallTarget(const QString &name, QObject *target){
    if(name == kFirstPage || name == kPreviousPage || name == kNextPage || name == kLastPage){
        QAbstractButton *button = qobject_cast<QAbstractButton*>(target);
        if(name == kFirstPage) disconnect(button,&QAbstractButton::clicked,this,&ButtonPage::button_firstPage_onClicked);
        if(name == kPreviousPage) disconnect(button,&QAbstractButton::clicked,this,&ButtonPage::button_previousPage_onClicked);
        if(name == kNextPage) disconnect(button,&QAbstractButton::clicked,this,&ButtonPage::button_nextPage_onClicked);
        if(name == kLastPage) disconnect(button,&QAbstractButton::clicked,this,&ButtonPage::button_lastPage_onClicked);
    }
    else if(name == kPageSwitch){
        QLineEdit *lineEdit = qobject_cast<QLineEdit*>(target);
        if(lineEdit){
            lineEdit->setValidator(nullptr);
            disconnect(lineEdit,&QLineEdit::textEdited,this,&ButtonPage::lineEdit_pageSwitch_onTextEdited);
            disconnect(lineEdit,&QLineEdit::editingFinished,this,&ButtonPage::lineEdit_pageSwitch_onEditingFinished);
        }
    }
    else {

    }
}

QAbstractButton *ButtonPage::first(){
    return qobject_cast<QAbstractButton*>(target(kFirstPage));
}
QAbstractButton *ButtonPage::previous(){
    return qobject_cast<QAbstractButton*>(target(kPreviousPage));
}
QLabel *ButtonPage::page(){
    return qobject_cast<QLabel*>(target(kPageIndicator));
}
QAbstractButton *ButtonPage::next(){
    return qobject_cast<QAbstractButton*>(target(kNextPage));
}
QAbstractButton *ButtonPage::last(){
    return qobject_cast<QAbstractButton*>(target(kLastPage));
}
QLineEdit *ButtonPage::pageSwitch(){
    return qobject_cast<QLineEdit*>(target(kPageSwitch));
}

void ButtonPage::setCountLess(int count, bool &needUpdate){
    if(count == _count){
        return ;
    }
    int lastPageCount = _pageCount;
    _count = count;
    _pageCount = _count/_countPerPage;
    if(_count%_countPerPage){
        ++_pageCount;
    }

    // 如果当前页总数是减少
    if(_pageCount<lastPageCount){
        // 当前页编号是修改前的最后一页
        if(_pageIndex+1>=lastPageCount){
            if(_pageCount>0){
                setPageIndexLess(_pageCount-1,needUpdate);
            }
            else {
                setPageIndexLess(0,needUpdate);
            }
        }
    }

    // 如果当前页总数没有减少 && 当前页编号是最后一页
    if(_pageCount==lastPageCount && _pageIndex+1>=_pageCount){
        needUpdate = true;
    }

    // 如果当前页总数在增加
    if(_pageCount>lastPageCount){
    }

    updateButtonState();
    updatePageTitle();
    updatePageSwitch();
}
void ButtonPage::setCount1(int count){
    bool needUpdate = false;
    setCountLess(count,needUpdate);
    if(needUpdate){
        emit sigEvent(kSigNeedUpdate,QVariant());
    }
}
void ButtonPage::setPageIndexLess(int index, bool &needUpdate){
    if(index>_pageCount){
        return;
    }
    int temp = _pageIndex;
    _pageIndex = index;
    updateButtonState();
    updatePageTitle();

    if(temp != index){
        needUpdate = true;
    }
}
void ButtonPage::setPageIndex1(int index){
    if(index>_pageCount || index<0 || (_pageCount>0&&index==_pageCount)){
        return;
    }
    int temp = _pageIndex;
    _pageIndex = index;
    updateButtonState();
    updatePageTitle();

    if(temp != index){
        emit sigEvent(kSigNeedUpdate,QVariant());
    }
}
void ButtonPage::updatePageTitle(){
    page()->setText(QString("%1/%2").arg(_pageIndex<0?1:_pageIndex+1).arg(0==_pageCount?1:_pageCount));
}
void ButtonPage::updateButtonState(){
    first()->setEnabled(_pageIndex>0);
    previous()->setEnabled(_pageIndex>0);
    next()->setEnabled(_pageIndex>=0&&_pageIndex+1<_pageCount);
    last()->setEnabled(_pageIndex>=0&&_pageIndex+1<_pageCount);
}
void ButtonPage::updatePageSwitch(){
    QLineEdit *lineEdit = pageSwitch();
    if(!lineEdit){
        return;
    }
    lineEdit->setValidator(new QIntValidator(1,_pageCount));
    lineEdit->setText("");
}

void ButtonPage::button_firstPage_onClicked(){
    if(_pageIndex<0|| _pageCount<=1){
        xxLog("[BUG] invalid param. count:%d countPerPage:%d pageCount:%d pageIndex:%d",_count,_countPerPage,_pageCount,_pageIndex);
        return;
    }
    setPageIndex1(0);
}
void ButtonPage::button_previousPage_onClicked(){
    if(_pageIndex<0|| _pageCount<=1){
        xxLog("[BUG] invalid param. count:%d countPerPage:%d pageCount:%d pageIndex:%d",_count,_countPerPage,_pageCount,_pageIndex);
        return;
    }
    setPageIndex1(_pageIndex-1);
}
void ButtonPage::button_nextPage_onClicked(){
    if(_pageIndex>=_pageCount|| _pageCount<=1){
        xxLog("[BUG] invalid param. count:%d countPerPage:%d pageCount:%d pageIndex:%d",_count,_countPerPage,_pageCount,_pageIndex);
        return;
    }
    setPageIndex1(_pageIndex+1);
}
void ButtonPage::button_lastPage_onClicked(){
    if(_pageIndex>=_pageCount || _pageCount<=1){
        xxLog("[BUG] invalid param. count:%d countPerPage:%d pageCount:%d pageIndex:%d",_count,_countPerPage,_pageCount,_pageIndex);
        return;
    }
    setPageIndex1(_pageCount-1);
}
void ButtonPage::lineEdit_pageSwitch_onTextEdited(const QString &text){
    QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender());
    QString t = text;
    int p = 0;
    if(nullptr!=lineEdit->validator() && QValidator::Acceptable != lineEdit->validator()->validate(t,p)){
        QString s;
        lineEdit->validator()->fixup(s);
        lineEdit->setText(s);
    }
}
void ButtonPage::lineEdit_pageSwitch_onEditingFinished(){
    QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender());
    setPageIndex1(lineEdit->text().toInt()-1);
    lineEdit->setText("");
}
